//
// Created by Administrator on 2022/11/12 0012.
//

#include <onix/mutex.h>
#include <onix/onix.h>
#include <onix/interrupt.h>
#include <onix/assert.h>
#include <onix/task.h>

void mutex_init(mutex_t *mutex)
{
    mutex->value = FALSE;
    list_init(&mutex->waiters);
}

void mutex_lock(mutex_t *mutex)
{
    bool interrupt = interrupt_disable();

    task_t *task = running_task();
    while (mutex->value == TRUE) {
        task_block(task, &mutex->waiters, TASK_BLOCKED);
    }

    assert(mutex->value == FALSE);
    mutex->value++;
    assert(mutex->value == TRUE);
    set_interrupt_state(interrupt);
}

void mutex_unlock(mutex_t *mutex)
{
    bool interrupt = interrupt_disable();
    assert(mutex->value == TRUE);
    mutex->value--;
    assert(mutex->value == FALSE);

    if (!list_empty(&mutex->waiters)) {
        task_t *task = element_entry(task_t, node, mutex->waiters.tail.prev);
        assert(task->magic == ONIX_MAGIC);
        task_unblock(task);
        task_yield();
    }
    set_interrupt_state(interrupt);
}

// 自旋锁初始化
void lock_init(lock_t *lock)
{
    lock->holder = NULL;
    lock->repeat = 0;
    mutex_init(&lock->mutex);
}

// 尝试持有锁
void lock_acquire(lock_t *lock)
{
    task_t *current = running_task();
    if (lock->holder != current)
    {
        mutex_lock(&lock->mutex);
        lock->holder = current;
        assert(lock->repeat == 0);
        lock->repeat = 1;
    }
    else
    {
        lock->repeat++;
    }
}

// 释放锁
void lock_release(lock_t *lock)
{
    task_t *current = running_task();
    assert(lock->holder == current);
    if (lock->repeat > 1)
    {
        lock->repeat--;
        return;
    }

    assert(lock->repeat == 1);

    lock->holder = NULL;
    lock->repeat = 0;
    mutex_unlock(&lock->mutex);
}